package cn.edu.shu.wechat.core.token;

import java.util.Date;

import javax.servlet.http.HttpUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.google.gson.JsonObject;

import cn.edu.shu.wechat.core.http.HttpsUtil;

public abstract class Token {
	private static final Logger logger = LoggerFactory.getLogger(Token.class);
	private String token; // token
	private long expires; // token有效时间
	private long tokenTime; // token产生时间
	private int redundance = 10 * 1000; // 冗余时间，提前10秒就去请求新的token

	public String getToken() {
		return token;
	}

	public long getExpires() {
		return expires;
	}

	/**
	 * 发送https请求，并转换赋值
	 * @return
	 */
	public boolean request() {
		return parseData(HttpsUtil.sendGetRequest(accessTokenUrl()));
	}

	/**
	 * 解析token数据
	 * 
	 * @param JsonObject data 调用微信接口解析得到的json对象
	 * @return
	 */
	private boolean parseData(JsonObject data) {

		String tokenName = tokenName();
		String expiresInName = expiresInName();
		if (data != null) {
			if (data.has(tokenName) && data.has(expiresInName)) {
				this.token = data.get(tokenName).getAsString();
				this.expires = data.get(expiresInName).getAsLong();
				logger.info("the token is :"+this.token);
				logger.info("the expires is :"+this.expires);
				return true;
			} else {
				logger.error("the json object does not have proertity named :" + tokenName + " and " + expiresInName);
				return false;
			}
		} else {
			logger.error("can not parse json objecet,becase the object is empty!");
			return false;
		}

	}

	/**
	 * token的参数名称
	 * 
	 * @return
	 */
	protected abstract String tokenName();

	/**
	 * expireIn的参数名称
	 * 
	 * @return
	 */
	protected abstract String expiresInName();

	/**
	 * 组织accesstoken的请求utl
	 * 
	 * @return
	 */
	protected abstract String accessTokenUrl();

	/**
	 * accessToken 是否有效
	 * 
	 * @return true:有效，false: 无效
	 */
	public boolean isValid() {
		// 黑名单判定法
		if (StringUtils.isEmpty(token))
			return false;
		if (this.expires <= 0)
			return false;
		// 过期
		if (isExpire())
			return false;
		return true;
	}

	/**
	 * 是否过期
	 * 
	 * @return true 过期 false：有效
	 */
	private boolean isExpire() {
		Date currentDate = new Date();
		long currentTime = currentDate.getTime();
		long expiresTime = expires * 1000 - redundance;
		// 判断是否过期
		if ((tokenTime + expiresTime) > currentTime)
			return false;
		return true;
	}

}
